<script lang="ts" setup>
import toLine from '@/utils';
import { computed, onMounted, ref, watch } from 'vue';
import cloneDeep from 'lodash/cloneDeep';
import { TableOptions } from './types';

import { useEditCell } from '../hooks/useEditCell';

const props = withDefaults(
  defineProps<{
    options: TableOptions[];
    data: any[];
    elementLoadingText?: string;
    elementLoadingSpinner?: string;
    elementLoadingSvg?: string;
    elementLoadingBackground?: string;
    editIcon?: string;
    isEditRow?: boolean;
    editRowTarget?: boolean;
    pagination?: boolean;
    paginationAlign?: 'left' | 'center' | 'right';
    currentPage: number;
    pageSize?: number;
    pageSizes?: number[];
    total?: number;
  }>(),
  {
    elementLoadingText: '加载中',
    elementLoadingBackground: '',
    elementLoadingSpinner: '',
    elementLoadingSvg: '',
    editIcon: 'edit',
    isEditRow: false,
    editRowTarget: false,
    pagination: false,
    paginationAlign: 'left',
    pageSize: 10,
    pageSizes: () => [10, 50, 100, 200],
    total: 10,
  },
);

// 过滤操作项之后的配置
const tableOption = computed(() => props.options.filter((item) => !item.action));
// 操作项
const actionOption = computed(() => props.options.find((item) => item.action));

const isLoading = computed(() => !props.data);

const emits = defineEmits([
  'confirm',
  'cancle',
  'update:editRowTarget',
  'size-change',
  'current-change',
  'update:currentPage',
]);

const { clickEditIcon, closeEdit, confirmEdit, currentEdit } = useEditCell(emits);

const tableData = ref<any[]>(cloneDeep(props.data));

let flag = false;

onMounted(() => {
  tableData.value.forEach((item) => {
    item.rowEdit = false;
  });
});

watch(
  () => props.editRowTarget,
  () => {
    flag = true;
  },
);

// 点击行的事件
const rowClick = (row: any, column: any) => {
  // 判断是否是点击的操作项
  if (column.label === actionOption.value?.label) {
    if (props.isEditRow) {
      !row.rowEdit && (flag = props.editRowTarget);
      if (flag) {
        row.rowEdit = props.editRowTarget;
        // 重置其他数据的rowEdit
        tableData.value.forEach((item) => {
          if (item !== row) item.rowEdit = false;
        });
        flag = false;
      }
    }
  }
};

//
const tableCurrentPage = ref<number>(props.currentPage);

// 如果data的数据变了 要重新给tableData赋值
// 只需要监听一次就可以了
watch(
  () => props.data,
  (val) => {
    tableData.value = val;
  },
  { deep: true },
);

watch(
  () => props.currentPage,
  (val) => {
    tableCurrentPage.value = val;
  },
);

watch(
  () => tableCurrentPage.value,
  (val) => {
    emits('update:currentPage', val);
  },
);

const handleSizeChange = (val: number) => {
  emits('size-change', val);
};

const handleCurrentChange = (val: number) => {
  emits('current-change', val);
};
</script>

<template>
  <div class="mn-table">
    <el-table
      v-loading="isLoading"
      :data="tableData"
      :element-loading-text="elementLoadingText"
      :element-loading-spinner="elementLoadingSpinner"
      :element-loading-svg="elementLoadingSvg"
      :element-loading-background="elementLoadingBackground"
      v-bind="$attrs"
      height="100%"
      class="mn-table-body"
      @row-click="rowClick"
    >
      <template v-for="(item, index) in tableOption" :key="index">
        <el-table-column :label="item.label" :align="item.align" :width="item.width" :fixed="item.fixed">
          <template #default="scope">
            <template v-if="scope.row.rowEdit">
              <el-input v-model="scope.row[item.prop!]" size="small"></el-input>
            </template>
            <template v-else>
              <template v-if="scope.$index + scope.column.id === currentEdit">
                <div class="table-editing">
                  <el-input v-model="scope.row[item.prop!]" class="table-editing-input" size="small"></el-input>
                  <slot v-if="$slots.cellEdit" name="cellEdit" :scope="scope"></slot>
                  <div v-else class="table-editing-icons">
                    <el-icon-check class="table-editing-check" @click.stop="confirmEdit(scope)"></el-icon-check>
                    <el-icon-close class="table-editing-close" @click.stop="closeEdit(scope)"></el-icon-close>
                  </div>
                </div>
              </template>
              <span v-else class="table-cell">
                <span v-if="item.slot" class="table-cell-content">
                  <slot :name="item.slot" :row="scope.row" :scope="scope"></slot>
                </span>
                <span v-else class="table-cell-content">{{
                  item.prop ? (scope.row[item.prop] ? scope.row[item.prop] : '-') : '-'
                }}</span>
                <component
                  :is="`el-icon-${toLine(editIcon)}`"
                  v-if="item.editable"
                  class="edit"
                  @click.stop="clickEditIcon(scope)"
                ></component>
              </span>
            </template>
          </template>
        </el-table-column>
      </template>
      <el-table-column
        v-if="actionOption"
        :label="actionOption.label"
        :align="actionOption.align"
        :width="actionOption.width"
        :fixed="actionOption.fixed"
      >
        <template #default="scope">
          <slot v-if="scope.row.rowEdit" name="editAction" :scope="scope"></slot>
          <slot v-else name="action" :scope="scope"></slot>
        </template>
      </el-table-column>
    </el-table>
    <div v-if="pagination && !isLoading" class="pagination">
      <el-pagination
        v-model:currentPage="tableCurrentPage"
        :page-sizes="pageSizes"
        :page-size="pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      ></el-pagination>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.mn-table {
  display: flex;
  flex-flow: column;
  flex: 1;
  justify-content: space-between;
  height: 100%;
  .table-cell {
    display: flex;
    word-break: normal;
    align-items: center;
    .table-cell-content {
      flex: 1;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: normal;
    }
    .edit {
      margin-left: 4px;
      cursor: pointer;
    }
  }
  .table-editing {
    display: flex;
    align-items: center;
    &-input {
      flex: 1;
    }
    &-icons {
      display: flex;
      align-items: center;
      .table-editing-check {
        color: #409eff;
        cursor: pointer;
        &:hover {
          color: #79bbff;
        }
      }
      .table-editing-close {
        color: #f56c6c;
        cursor: pointer;
        &:hover {
          color: #f89898;
        }
      }
    }
  }
  .pagination {
    display: flex;
    justify-content: space-between;
  }
}
</style>
